import logging
import os
from flask import Blueprint, jsonify, request
from app.utils.aoi_utils import read_file_with_multiple_encodings, detect_aoi_file_type, unify_aoi_data
from mysql_tool.mysql_tool import MySQLTool
from app.config.paths import SMT2_AOI_PATH

smt2_aoi_bp = Blueprint('smt2_aoi', __name__)

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# 定义SMT2 AOI数据文件的Linux路径
# SMT2_AOI_PATH = "/mnt/smt2/aoi/Result"


def get_smt_npm_scan_record(serial_number):
    """查询锡膏信息（根据流水号获取同批次所有流水号）"""
    logger.info(f"查询流水号批次信息: {serial_number}")

    # 创建数据库连接
    mysql_tool = MySQLTool()

    # 使用参数化查询防止SQL注入
    smt_sql = """
              SELECT batch_code, \
                     serial_number
              FROM smt_npm_scan_record
              WHERE batch_code = (SELECT a.batch_code FROM smt_npm_scan_record AS a WHERE a.serial_number = %s LIMIT 1) \
              """

    logger.info(f"执行SQL: {smt_sql}, 参数: {serial_number}")
    results = mysql_tool.execute_query(smt_sql, (serial_number,))

    smt_data = []
    for row in results:
        item = {
            "batchCode": row[0],
            "serialNumber": row[1],
        }
        smt_data.append(item)

    logger.info(f"找到同批次流水号: {len(smt_data)}个")
    return smt_data


@smt2_aoi_bp.route('/api/smt2aoi/query/<serial_number>', methods=['GET'])
def query_smt2_aoi_data(serial_number):
    """SMT2 AOI数据查询接口，通过流水号查询对应的PEMTRON设备AOI测试数据"""
    try:
        if not serial_number:
            return jsonify({"success": False, "message": "流水号码不能为空"}), 400

        logger.info(f"查询SMT2 AOI数据，流水号: {serial_number}")

        # 获取同批次所有流水号
        batch_serials = get_smt_npm_scan_record(serial_number)
        if not batch_serials:
            logger.warning(f"未找到流水号 {serial_number} 的批次信息")
            all_serials = [{"serialNumber": serial_number}]
        else:
            all_serials = batch_serials
            logger.info(f"同批次共有 {len(all_serials)} 个流水号")

        import glob

        # 遍历所有流水号查找文件
        for serial_data in all_serials:
            current_serial = serial_data["serialNumber"]
            logger.info(f"查找流水号 {current_serial} 的AOI文件")

            # 精确匹配流水号开头的文件
            pattern = os.path.join(SMT2_AOI_PATH, f"{current_serial}_*")
            matching_files = glob.glob(pattern)

            # 如果找不到精确匹配，则尝试查找包含流水号的文件
            if not matching_files:
                pattern = os.path.join(SMT2_AOI_PATH, f"*{current_serial}*")
                matching_files = glob.glob(pattern)

            # 如果找到匹配文件，无论能否解析都立即处理并返回结果
            if matching_files:
                logger.info(f"找到匹配的文件: {matching_files[0]}")

                # 尝试解析第一个匹配的文件
                try:
                    file_path = matching_files[0]
                    file_content = read_file_with_multiple_encodings(file_path)

                    if file_content is None:
                        return jsonify({
                            "success": False,
                            "message": "找到文件但无法读取内容",
                            "files": [file_path],
                            "original_serial_number": serial_number
                        }), 404

                    parsed_data = detect_aoi_file_type(file_content, os.path.basename(file_path))
                    if parsed_data:
                        # 接受所有类型��AOI数据，不只是PEMTRON
                        unified_data = unify_aoi_data(parsed_data)
                        unified_data["serial_number"] = current_serial

                        return jsonify({
                            "success": True,
                            "data": [unified_data],
                            "file_path": file_path,
                            "device_type": parsed_data["device_type"],
                            "used_serial_number": current_serial,
                            "original_serial_number": serial_number
                        })
                    else:
                        return jsonify({
                            "success": False,
                            "message": "找到文件但无法解析数据",
                            "files": [file_path],
                            "original_serial_number": serial_number
                        }), 404

                except Exception as e:
                    logger.error(f"处理文件失败 {file_path}: {str(e)}")
                    return jsonify({
                        "success": False,
                        "message": f"文件处理失败: {str(e)}",
                        "files": [file_path],
                        "original_serial_number": serial_number
                    }), 404

        # 如果遍历完所有流水号仍未找到匹配文件
        return jsonify({
            "success": False,
            "message": f"未找到流水号 {serial_number} 及同批次产品的AOI数据文件",
            "original_serial_number": serial_number
        }), 404

    except Exception as e:
        logger.error(f"查询SMT2 AOI信息失败: {str(e)}")
        return jsonify({
            "success": False,
            "message": f"查询失败: {str(e)}"
        }), 500



@smt2_aoi_bp.route('/api/smt2aoi/dashboard', methods=['GET'])
def get_recent_smt2_aoi_data():
    """获取最近几小时的SMT2 AOI数据用于控制面板展示"""
    try:
        import glob
        import time
        from datetime import datetime, timedelta

        # 获取参数中指���的小时数，默认3小时
        hours = request.args.get('hours', 3, type=int)
        logger.info(f"获取最近{hours}小时的SMT2 AOI数据")

        # 计算时间阈值
        current_time = time.time()
        time_threshold = current_time - (hours * 60 * 60)

        # 获取目录下所有文件
        all_files = glob.glob(os.path.join(SMT2_AOI_PATH, "*"))

        # 过滤出最近n小时内修改的文件
        recent_files = [file for file in all_files if os.path.getmtime(file) >= time_threshold]

        logger.info(f"找到最近{hours}小时内的文件数量: {len(recent_files)}")

        if not recent_files:
            return jsonify({
                "success": True,
                "message": f"未找到最近{hours}小时内的AOI数据文件",
                "data": []
            })

        # 处理找到的文件
        result_data = []
        summary_stats = {
            "total_files": len(recent_files),
            "processed_files": 0,
            "pass_count": 0,
            "fail_count": 0,
            "defect_types": {},
            "hourly_data": {}
        }

        for file_path in recent_files:
            try:
                file_content = read_file_with_multiple_encodings(file_path)

                if file_content is None:
                    logger.warning(f"无法读取文件内容: {file_path}")
                    continue

                parsed_data = detect_aoi_file_type(file_content, os.path.basename(file_path))

                if parsed_data:
                    # 统一数据格式
                    unified_data = unify_aoi_data(parsed_data)

                    # 提取文件名中的流水号
                    file_name = os.path.basename(file_path)
                    serial_number = file_name.split('_')[0] if '_' in file_name else "unknown"
                    unified_data["serial_number"] = serial_number

                    # 添加文件修改时间
                    modified_time = datetime.fromtimestamp(os.path.getmtime(file_path))
                    file_time = modified_time.strftime("%Y-%m-%d %H:%M:%S")
                    hour_key = modified_time.strftime("%Y-%m-%d %H:00")

                    # 提取控制面板所需数据
                    dashboard_data = extract_dashboard_data(unified_data, parsed_data)

                    # 更新统计信息
                    summary_stats["processed_files"] += 1
                    if dashboard_data["pass_status"] == "PASS":
                        summary_stats["pass_count"] += 1
                    else:
                        summary_stats["fail_count"] += 1

                    # 更新缺陷类型统计
                    for defect_type, count in dashboard_data["defect_types"].items():
                        if defect_type in summary_stats["defect_types"]:
                            summary_stats["defect_types"][defect_type] += count
                        else:
                            summary_stats["defect_types"][defect_type] = count

                    # 更新小时数据
                    if hour_key not in summary_stats["hourly_data"]:
                        summary_stats["hourly_data"][hour_key] = {
                            "total": 0, "pass": 0, "fail": 0, "defects": 0
                        }

                    summary_stats["hourly_data"][hour_key]["total"] += 1
                    if dashboard_data["pass_status"] == "PASS":
                        summary_stats["hourly_data"][hour_key]["pass"] += 1
                    else:
                        summary_stats["hourly_data"][hour_key]["fail"] += 1
                    summary_stats["hourly_data"][hour_key]["defects"] += dashboard_data["defect_count"]

                    # 构建结果项
                    result_item = {
                        "file_path": file_path,
                        "file_name": file_name,
                        "serial_number": serial_number,
                        "file_time": file_time,
                        "device_type": parsed_data["device_type"],
                        "dashboard_data": dashboard_data
                    }

                    result_data.append(result_item)
                else:
                    logger.warning(f"无法解析文件数据: {file_path}")

            except Exception as e:
                logger.error(f"处理文件失败 {file_path}: {str(e)}")
                continue

        # 按时间降序排序结果
        result_data.sort(key=lambda x: x["file_time"], reverse=True)

        # 转换小时数据为列表，便于前端处理
        hourly_list = []
        for hour, data in summary_stats["hourly_data"].items():
            hourly_list.append({
                "hour": hour,
                "total": data["total"],
                "pass": data["pass"],
                "fail": data["fail"],
                "defects": data["defects"]
            })

        # 按时间升序排序
        hourly_list.sort(key=lambda x: x["hour"])
        summary_stats["hourly_data"] = hourly_list

        return jsonify({
            "success": True,
            "summary": summary_stats,
            "data": result_data
        })

    except Exception as e:
        logger.error(f"获取AOI控制面板数据失败: {str(e)}")
        return jsonify({
            "success": False,
            "message": f"查询失败: {str(e)}"
        }), 500


def extract_dashboard_data(unified_data, parsed_data):
    """从统一格式的AOI数据中提取控制面板所需的关键数据"""
    dashboard_data = {
        "pass_status": unified_data.get("pass_status", "FAIL"),
        "component_count": 0,
        "defect_count": 0,
        "defect_types": {},
        "defect_locations": []
    }

    # 提取组件信息
    if "components" in unified_data:
        components = unified_data["components"]
        dashboard_data["component_count"] = len(components)

        # 计算缺陷数量和类型
        defect_count = 0
        defect_types = {}
        defect_locations = []

        for component in components:
            if component.get("has_defect", False):
                defect_count += 1

                defect_type = component.get("defect_type", "Unknown")
                if defect_type in defect_types:
                    defect_types[defect_type] += 1
                else:
                    defect_types[defect_type] = 1

                # 收集缺陷位置信息用于可视化
                defect_locations.append({
                    "id": component.get("id", ""),
                    "name": component.get("name", ""),
                    "position": {
                        "x": component.get("x", 0),
                        "y": component.get("y", 0)
                    },
                    "type": defect_type
                })

        dashboard_data["defect_count"] = defect_count
        dashboard_data["defect_types"] = defect_types
        dashboard_data["defect_locations"] = defect_locations

    # 添加设备特定信息
    device_type = parsed_data.get("device_type", "")
    if device_type:
        dashboard_data["device_info"] = {
            "type": device_type,
            "inspection_time": parsed_data.get("inspection_time", ""),
            "pcb_name": parsed_data.get("pcb_name", ""),
            "board_id": parsed_data.get("board_id", "")
        }

    return dashboard_data
